package com.timk.goserver.server.servlets;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.Session;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.SymbolAxis;
import org.jfree.chart.entity.StandardEntityCollection;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import com.keypoint.PngEncoder;
import com.timk.goserver.server.model.RatingEntry;
import com.timk.goserver.server.model.ServerUserInfo;
import com.timk.goserver.server.util.HibernateUtil;

/**
 * Generates rating graphs
 * @author TKington
 *
 */
public class RatingGraphServlet extends HttpServlet {
	private static final String [] rankLabels = { "20k", "19k", "18k", "17k", "16k",
		"15k", "14k", "13k", "12k", "11k", "10k", "9k", "8k", "7k", "6k", "5k",
		"4k", "3k", "2k", "1k", "1d", "2d", "3d", "4d", "5d", "6d", "7d", "8d", "9d"};
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String userid = request.getParameter("id"); 
		
		Session hbSession = HibernateUtil.startTrans();

		try {
			ServerUserInfo user = ServerUserInfo.findUser(userid, hbSession);
			
			if(user == null) {
				response.getWriter().println("User " + userid + " does not exist");
				return;
			}
			
			JFreeChart chart = createChart(user);
			BufferedImage chartImage = createImage(chart);
			response.setContentType("image/png");
			PngEncoder encoder = new PngEncoder(chartImage, false, 0, 9);
			response.getOutputStream().write(encoder.pngEncode());
		} finally {
			hbSession.getTransaction().commit();
		}
	}

	// Process the HTTP Post request
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

	private JFreeChart createChart(ServerUserInfo user) {
		TimeSeries data = new TimeSeries("Rating", Millisecond.class);
		
		List hist = user.getRatingHistory();
		
		int minRating = 9999;
		int maxRating = 100;
		
		for (Iterator iter = hist.iterator(); iter.hasNext();) {
			RatingEntry entry = (RatingEntry) iter.next();
			int rating = entry.getRating();
			minRating = Math.min(minRating, rating);
			maxRating = Math.max(maxRating, rating);
		}
		
		minRating = minRating / 100 * 100;
		maxRating = (maxRating + 99) / 100 * 100;

		for (Iterator iter = hist.iterator(); iter.hasNext();) {
			RatingEntry entry = (RatingEntry) iter.next();
			double value = (entry.getRating() - minRating) / 100.0;
			data.add(new Millisecond(entry.getDate()), value);
		}
		
		JFreeChart chart = ChartFactory.createTimeSeriesChart(
				"Rating history for " + user.getUsername(), // chart title
				"",
				"Rating",
				new TimeSeriesCollection(data), // data
				false, // include legend
				false, // tooltips
				false // urls
				);

		XYPlot plot = (XYPlot) chart.getPlot();
		plot.setNoDataMessage("No data available");
		plot.setOutlinePaint(Color.white);

		String [] labels = genLabels(minRating, maxRating);
		SymbolAxis axis = new SymbolAxis("", labels);
		axis.setGridBandsVisible(false);
		plot.setRangeAxis(axis);
		
		return chart;
	}
	
	private String [] genLabels(int min, int max) {
		int startIndex = (min - 100) / 100;
		int num = (max - min) / 100 + 1;
		
		String [] labels = new String[num];
		for(int i = 0; i < num; i++) {
			labels[i] = rankLabels[startIndex + i];
		}
		
		return labels;
	}
	
	private static BufferedImage createImage(JFreeChart chart) {
		ChartRenderingInfo info = new ChartRenderingInfo(
				new StandardEntityCollection());
		return chart.createBufferedImage(500, 375, info);
	}

}
